package com.tinem.platform.module.starter.session;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.tinem.platform.client.user.SessionClient;
import com.tinem.platform.module.commons.util.SessionUtil;
import com.tinem.platform.module.pojo.co.JwtPropertyName;
import com.tinem.platform.module.pojo.vo.IdBlankVo;
import com.tinem.platform.module.pojo.vo.auth.session.UserSessionToken;
import com.tinem.platform.module.pojo.vo.error.UserException;
import com.tinem.platform.module.starter.sdk.MessageCode;
import com.tinem.platform.module.starter.web.context.GatewayContext;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

public abstract class SessionAbstract {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Resource
    SessionClient sessionClient;

    /**
     * 判断session是否存在
     * @return
     */
    public boolean isSession(){
        String jit = GatewayContext.getJwtJit();
        if(StrUtil.isEmpty(jit)){
            return false;
        }else if(stringRedisTemplate.hasKey(getRedisKeySessionId())){
            return true;
        }
        return false;
    }

    public void startSession(String jwt, Map<String,String> map){
        startSession(jwt,map,null);
    }
    /**
     * session 启动
     * @param jwt jwt
     * @param map session 附加属性
     * @param authorize 权限信息
     */
    public void startSession(String jwt, Map<String,String> map, Collection<String> authorize){
        final JWT j = JWTUtil.parseToken(jwt);
        String jit = j.getPayloads().getStr(JwtPropertyName.JTI);
        Long exp = j.getPayloads().getLong(JwtPropertyName.EXP);
        String jitRedisKey = SessionUtil.getRedisKeySessionId(jit);
        stringRedisTemplate.opsForHash().putAll(jitRedisKey,map);
        stringRedisTemplate.expire(jitRedisKey,exp - System.currentTimeMillis()/1000, TimeUnit.SECONDS);
        if(CollUtil.isNotEmpty(authorize)){
            String redisKeySessionIdAuthorize = SessionUtil.getRedisKeySessionIdAuthorize(jitRedisKey);
            stringRedisTemplate.opsForSet().add(redisKeySessionIdAuthorize,authorize.toArray(new String[0]));
            stringRedisTemplate.expire(redisKeySessionIdAuthorize,exp - System.currentTimeMillis()/1000, TimeUnit.SECONDS);
        }
    }

    /**
     * 在sesison中存储数据
     * @param key
     */
    public void setAttribute(String key,String value){
        if(!isSession()){
            throw new UserException(MessageCode.ERROR_SESSION_NOT_FIND);
        }
        stringRedisTemplate.opsForHash().put(getRedisKeySessionId(),key,value);
    }

    /**
     * 获取session中的数据
     * @param key
     */
    public String getAttribute(String key){
        if(!isSession()){
            throw new UserException(MessageCode.ERROR_SESSION_NOT_FIND);
        }
        return (String) stringRedisTemplate.opsForHash().get(getRedisKeySessionId(),key);
    }
    /**
     * 获取session中的所有数据
     *
     */
    public Map<String, String> getAttributeAll(){
        if(!isSession()){
            throw new UserException(MessageCode.ERROR_SESSION_NOT_FIND);
        }
        Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(getRedisKeySessionId());
        Map<String, String> res = new HashMap();
        map.entrySet().forEach(e->{
            res.put((String) e.getKey(), (String) e.getValue());
        });
        return res;
    }

    /**
     * 清理session 所有数据
     */
    public Boolean clear(){
        if(!isSession()){
            return true;
        }
        return stringRedisTemplate.delete(getRedisKeySessionId());
    }
    public Boolean clear(final long timeout, final TimeUnit unit){
        if(!isSession()){
            return true;
        }
        return stringRedisTemplate.expire(getRedisKeySessionId(),timeout,unit);
    }
    public static String getRedisKeySessionId(){
        return SessionUtil.getRedisKeySessionId(GatewayContext.getJwtJit());
    }

    /**
     * 获取用户所有未过期的session
     * @param userId
     * @return
     */
    public List<UserSessionToken> getUserSession(String userId){
        IdBlankVo idBlankVo = new IdBlankVo();
        idBlankVo.setUuidToId(userId);
        return sessionClient.getAllSessionByUser(idBlankVo);
    }

    /**
     * 删除用户所有session
     * @param userId
     * @return
     */
    public void delAllSessionByUser(String userId){
        IdBlankVo idBlankVo = new IdBlankVo();
        idBlankVo.setUuidToId(userId);
        sessionClient.delAllSessionByUser(idBlankVo);
    }
}
